#include "score.h"
#include "ustjkeys.h"
#include "math.h"

static bool endFlag(QString& str,QString e)
{
    if(str.endsWith(e)) {
        str = str.remove(e);
        return true;
    }
    return false;
}


float QtauScore::checkInc(QString type, float lastpos)
{
    if(lastpos<=0.0f) return 0.0f;
    if(type=="DYN")
    {
        if(last_DYN>=lastpos) lastpos = last_DYN + 0.001f;
        last_DYN = lastpos;
        qDebug() << "last_DYN" << last_DYN;
    }
    else if(type=="PIT")
    {
        if(last_PIT>=lastpos) lastpos = last_PIT + 0.001f;
        last_PIT = lastpos;
    }
    return lastpos;
}


void QtauScore::fillTrack(QString type,QStringList events,synthNote* note)
{
    //special case: events.size == 0
    //type: DYN or PIT --> later pho
    for(int i=0;i<events.size();i++)
    {
        QStringList sub = events[i].split(",");
        if(sub.size()==2)
        {
            synthPoint p;
            auto x = sub[0];
            bool x_percent = endFlag(x,"%");
            auto y = sub[1];
            bool y_dB = endFlag(y,"dB");
            bool y_percent = endFlag(y,"%");

            p.x = QVariant(x).toFloat();
            p.y = QVariant(y).toFloat();
            if(y_dB && type=="DYN") {
                float old = p.y;
                p.y = static_cast<float>(pow(10,-p.y/20));
                qDebug() << "convert from dB" << old << "->" << p.y;
            }
            if(x_percent)
            {
                p.x *= 0.01f;
            }
            if(y_percent)
            {
                p.y *= 0.01f;
            }

            p.x = note->start + p.x * note->lenght; // set pos

            p.x = checkInc(type,p.x);

            //TODO check pos

            if(type=="DYN") note->dyn.push_back(p);
            if(type=="PIT") note->pit.push_back(p);

            // PIT units
            // midi note number : semitones
            // mudulation: add Hz
            // portamento -> take pitch of next note, 1p

            // UTAU mode2
            // portamento: p_length,p_start
            // VBR,v_len,v_cyc,v_dep,v_in,v_out,v_pha,v_pit

        }


    }
    // create common modulation ?

}


QtauScore::QtauScore(const QJsonArray& ust, TempoMap* tmap) {
    float lastNoteEndTime = 0;

    for (int i = 0; i < ust.count(); ++i) {
        auto o = ust[i].toObject();

        if (!o.contains(NOTE_KEY_NUMBER)) {
            continue;
        }

        synthNote note;

        int noteOffset = o[NOTE_PULSE_OFFSET].toInt();
        int noteLength = o[NOTE_PULSE_LENGTH].toInt();
        QString lyric = o[NOTE_LYRIC].toString();
        int pitch = o[NOTE_KEY_NUMBER].toInt();

        QString pit = o[NOTE_PITCH].toString();
        QString pho = o[NOTE_PHO].toString();
        QString dyn = o[NOTE_DYNAMICS].toString();

        DEVLOG_DEBUG("PIT"<<pit);
        DEVLOG_DEBUG("DYN"<<dyn);
        DEVLOG_DEBUG("PHO"<<pho);

        float timeSt;
        float timeEd;
        int barSt;
        int barEd;
        int st = noteOffset;
        int ed = noteOffset + noteLength - 1;
        tmap->getBar(st, timeSt, barSt, 0);
        tmap->getBar(ed, timeEd, barEd, 1);

        float rest = timeSt - lastNoteEndTime;

        if (rest < 0) {
            // invalid=true;
            break;
        }

        note.rest = rest;
        note.start = timeSt;
        note.lenght = timeEd - timeSt;
        note.pitch = pitch;
        note.lyric = lyric;

        note.pho = pho.split(" ");

        fillTrack("PIT",pit.split(" "),&note);
        fillTrack("DYN",dyn.split(" "),&note);

        lastNoteEndTime = timeEd;

        notes.push_back(note);
    }
    DEVLOG_DEBUG("done building score");
}

//TODO update interface
int QtauScore::getNoteCount() {
    return static_cast<int>(notes.size());//XX use size_t here
}

synthNote QtauScore::getNote(int index) {
    return notes[static_cast<size_t>(index)];//XX size_t here
}
